#include "gtimer.h"

QueueHandle_t queue;

/**
 * @brief       通用定时器回调函数
 * @param       timer: 定时器关联句柄
 * @param       edata: 包含报警值与当前计数值的结构体指针
 * @param       user_ctx: 传递给回调函数的参数
 * @retval      无
 */
bool IRAM_ATTR gtimer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
    LED_TOGGLE();

    /* 假设没有唤醒更高优先级的任务 */
    BaseType_t high_task_awoken=pdFALSE;

    queue=(QueueHandle_t)user_ctx;
    
    /* 从事件数据中检索计数值 */
    gptimer_event_t ele={
        .event_count=edata->count_value
    };

    /* 可选：通过操作系统队列将事件数据发送到其他任务 */
    xQueueSendFromISR(queue,&ele,&high_task_awoken);

    /* 重新配置报警值 */ 
    gptimer_alarm_config_t gtimer_alarm_config={
        .alarm_count=edata->alarm_value+1000000
    };
    gptimer_set_alarm_action(timer,&gtimer_alarm_config);

    /* 判断回调函数运行时是否唤醒更高优先级的任务 */
    return high_task_awoken==pdTRUE;
}

void gtimer_init(uint64_t count, uint64_t resolution)
{
    uint64_t set_count=0ULL;
    gptimer_config_t gtimer_init_strutc = {
        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
        .direction = GPTIMER_COUNT_UP,
        .resolution_hz = resolution
    };
    gptimer_handle_t gtimer_handle = NULL;
    gptimer_event_callbacks_t gtimer_event_callback={
        .on_alarm=gtimer_callback,
    };
    // ISR 中使用报警值重载与此处.flags.auto_reload_on_alarm=true冲突
    // 若 ISR 中调用了 gptimer_set_alarm_action 设定报警值
    // 则 .flags.auto_reload_on_alarm=false
    gptimer_alarm_config_t gtimer_alarm_config={
        .flags.auto_reload_on_alarm=true,
        .alarm_count=1000000,
        .reload_count=0ULL
    };

    ESP_LOGI("GPTIMER_ALARM", "配置通用定时器");
    // 创建通用定时器
    ESP_ERROR_CHECK(
        gptimer_new_timer(&gtimer_init_strutc, &gtimer_handle));
    /* 创建事件队列 */
    queue=xQueueCreate(10,sizeof(gptimer_event_t));
    /* 创建队列判断 */
    if(!queue)
    {
        ESP_LOGE("GPTIMER_ALARM", "创建队列失败");
        return;
    }
    /* 设置和获取计数值 */
    ESP_LOGI("GPTIMER_ALARM", "设置计数值");
    ESP_ERROR_CHECK(gptimer_set_raw_count(gtimer_handle,count));
    ESP_LOGI("GPTIMER_ALARM", "获取计数值");
    ESP_ERROR_CHECK(gptimer_get_raw_count(gtimer_handle,&set_count));
    ESP_LOGI("GPTIMER_ALARM", "定时器计数值： %"PRIu64, count);

    /* 注册事件回调函数 */
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(gtimer_handle,&gtimer_event_callback,queue));
    
    /* 设置报警动作 */
    ESP_LOGI("GPTIMER_ALARM", "开启定时器");
    ESP_ERROR_CHECK(gptimer_enable(gtimer_handle));
    ESP_ERROR_CHECK(gptimer_set_alarm_action(gtimer_handle,&gtimer_alarm_config));
    ESP_ERROR_CHECK(gptimer_start(gtimer_handle));

}


